package com.huitone.smspfm.redis.impl;

import java.net.SocketTimeoutException;
import java.util.ArrayList;
import java.util.List;

import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.springframework.data.redis.RedisConnectionFailureException;
import org.springframework.data.redis.core.script.RedisScript;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.huitone.smspfm.redis.BaseAbstractOpts;
import com.huitone.smspfm.redis.model.AppCanstant;

/**   
* @Title ScriptOpts.java 
* @Package com.huitone.smspfm.redis.impl 
* @Description TODO(用一句话描述该文件做什么) 
* @author ybliang   
* @date 2017年6月17日 下午6:53:44 
* @version V1.0   
*/
public class ScriptOpts extends BaseAbstractOpts<String, String> {
	
	private static final Logger logger = LogManager.getLogger(ScriptOpts.class);
	
	public long execute(RedisScript<Long> script, List<String> keys, Object... objects) {
		
		long curTryTimes = 0;
		
		boolean excuteSucc = false;
		
		long result = 0;
		
		do {
			try {
				curTryTimes ++;
				result = redisTemplate.execute(script, keys, objects);
				excuteSucc = true;
			} catch (Exception e) {
				if (e instanceof RedisConnectionFailureException) {
					excuteSucc = false;
					logger.error("从JedisPool获取连接失败, 尝试获取连接:" + curTryTimes + "次! RedisServer:" + getMasterAddressPort());
				} else if (e instanceof SocketTimeoutException) {
					excuteSucc = true;
					logger.error("SoketTimeout,命令已经发送到Redis上执行,但是在等待执行结果的时候SocketRead超时! RedisServer:" + getMasterAddressPort(), e);
				} else {
					excuteSucc = false;
					logger.error("RedisServer:" + getMasterAddressPort(), e);
				}
			}
			
			if (!excuteSucc && (curTryTimes >= AppCanstant.MAXTRYTIMES)) {
				StackTraceElement[] stackTrace = Thread.currentThread().getStackTrace();
				if (stackTrace != null) {
					StringBuffer buffer = new StringBuffer();
					for (StackTraceElement element:stackTrace) {
						buffer.append(element.getClassName() + "." + element.getMethodName() + " " + element.getLineNumber());
						buffer.append("\n");
					}
					logger.error("连续执行三次失败:\n" + buffer);
				}
				JSONObject json = new JSONObject();
				json.put("errorType", "redis");
				json.put("className", this.getClass().getSimpleName());
				json.put("numCnt", this.getNumCnt());
				json.put("method", "execute(RedisScript<Long> script, List<String> keys, Object... objects)");
				
				json.put("script", script.getScriptAsString());
				JSONArray arrayKey = new JSONArray();
				for(String key:keys){
					arrayKey.add(key);
					}
				json.put("keys", arrayKey);
				JSONArray arrayObject = new JSONArray();
				if (objects != null) {
					for (int i = 0; i < objects.length; i++) {
						arrayObject.add(objects[i]);
					}
				}
				json.put("objects", arrayObject);
				logger.error(json.toJSONString());
				configInit.initRedis(this.getNumCnt());
			}
			
		} while (!excuteSucc && (curTryTimes < AppCanstant.MAXTRYTIMES));
		
		return result;
	}
	
	@SuppressWarnings({ "rawtypes", "unchecked" })
	public List<List<String>> getSMCacheAndHash(RedisScript<List> script, List<String> keys, Object... objects) {
		
		long curTryTimes = 0;
		
		boolean excuteSucc = false;
		
		List<List<String>> result = new ArrayList<List<String>>();
		
		do {
			try {
				curTryTimes ++;
				result = redisTemplate.execute(script, keys, objects);
				excuteSucc = true;
			} catch (Exception e) {
				if (e instanceof RedisConnectionFailureException) {
					excuteSucc = false;
					logger.error("从JedisPool获取连接失败, 尝试获取连接:" + curTryTimes + "次! RedisServer:" + getMasterAddressPort());
				} else if (e instanceof SocketTimeoutException) {
					excuteSucc = true;
					logger.error("SoketTimeout,命令已经发送到Redis上执行,但是在等待执行结果的时候SocketRead超时! RedisServer:" + getMasterAddressPort(), e);
				} else {
					excuteSucc = false;
					logger.error("RedisServer:" + getMasterAddressPort(), e);
				}
			}
			
			if (!excuteSucc && (curTryTimes >= AppCanstant.MAXTRYTIMES)) {
				StackTraceElement[] stackTrace = Thread.currentThread().getStackTrace();
				if (stackTrace != null) {
					StringBuffer buffer = new StringBuffer();
					for (StackTraceElement element:stackTrace) {
						buffer.append(element.getClassName() + "." + element.getMethodName() + " " + element.getLineNumber());
						buffer.append("\n");
					}
					logger.error("连续执行三次失败:\n" + buffer);
				}
				JSONObject json = new JSONObject();
				json.put("errorType", "redis");
				json.put("className", this.getClass().getSimpleName());
				json.put("numCnt", this.getNumCnt());
				json.put("method", "getSMCacheAndHash(RedisScript<List> script, List<String> keys, Object... objects)");
				
				json.put("script", script.getScriptAsString());
				JSONArray arrayKey = new JSONArray();
				for(String key:keys){
					arrayKey.add(key);
					}
				json.put("keys", arrayKey);
				JSONArray arrayObject = new JSONArray();
				if (objects != null) {
					for (int i = 0; i < objects.length; i++) {
						arrayObject.add(objects[i]);
					}
				}
				json.put("objects", arrayObject);
				logger.error(json.toJSONString());
				configInit.initRedis(this.getNumCnt());
			}
			
			
		} while (!excuteSucc && (curTryTimes < AppCanstant.MAXTRYTIMES));
		
		return result;
	}
	
	@SuppressWarnings({ "rawtypes", "unchecked" })
	public List<List<String>> getHashList(RedisScript<List> script, List<String> keys, Object... objects) {
		
		long curTryTimes = 0;
		
		boolean excuteSucc = false;
		
		List<List<String>> result = new ArrayList<List<String>>();
		
		do {
			try {
				curTryTimes ++;
				result = redisTemplate.execute(script, keys, objects);
				excuteSucc = true;
			} catch (Exception e) {
				if (e instanceof RedisConnectionFailureException) {
					excuteSucc = false;
					logger.error("从JedisPool获取连接失败, 尝试获取连接:" + curTryTimes + "次! RedisServer:" + getMasterAddressPort());
				} else if (e instanceof SocketTimeoutException) {
					excuteSucc = true;
					logger.error("SoketTimeout,命令已经发送到Redis上执行,但是在等待执行结果的时候SocketRead超时! RedisServer:" + getMasterAddressPort(), e);
				} else {
					excuteSucc = false;
					logger.error("RedisServer:" + getMasterAddressPort(), e);
				}
			}
			
			if (!excuteSucc && (curTryTimes >= AppCanstant.MAXTRYTIMES)) {
				StackTraceElement[] stackTrace = Thread.currentThread().getStackTrace();
				if (stackTrace != null) {
					StringBuffer buffer = new StringBuffer();
					for (StackTraceElement element:stackTrace) {
						buffer.append(element.getClassName() + "." + element.getMethodName() + " " + element.getLineNumber());
						buffer.append("\n");
					}
					logger.error("连续执行三次失败:\n" + buffer);
				}
				JSONObject json = new JSONObject();
				json.put("errorType", "redis");
				json.put("className", this.getClass().getSimpleName());
				json.put("numCnt", this.getNumCnt());
				json.put("method", "getHashList(RedisScript<List> script, List<String> keys, Object... objects)");
				
				json.put("script", script.getScriptAsString());
				JSONArray arrayKey = new JSONArray();
				for(String key:keys){
					arrayKey.add(key);
					}
				json.put("keys", arrayKey);
				JSONArray arrayObject = new JSONArray();
				if (objects != null) {
					for (int i = 0; i < objects.length; i++) {
						arrayObject.add(objects[i]);
					}
				}
				json.put("objects", arrayObject);
				logger.error(json.toJSONString());
				configInit.initRedis(this.getNumCnt());
			}
			
		} while (!excuteSucc && (curTryTimes < AppCanstant.MAXTRYTIMES));
		
		return result;
	}

	@SuppressWarnings({ "rawtypes", "unchecked" })
	public List<String> getList(RedisScript<List> script, List<String> keys, Object... objects) {
		
		long curTryTimes = 0;
		
		boolean excuteSucc = false;
		
		List<String> result = new ArrayList<String>();
		
		do {
			try {
				curTryTimes ++;
				result = redisTemplate.execute(script, keys, objects);
				excuteSucc = true;
			} catch (Exception e) {
				if (e instanceof RedisConnectionFailureException) {
					excuteSucc = false;
					logger.error("从JedisPool获取连接失败, 尝试获取连接:" + curTryTimes + "次! RedisServer:" + getMasterAddressPort());
				} else if (e instanceof SocketTimeoutException) {
					excuteSucc = true;
					logger.error("SoketTimeout,命令已经发送到Redis上执行,但是在等待执行结果的时候SocketRead超时! RedisServer:" + getMasterAddressPort(), e);
				} else {
					excuteSucc = false;
					logger.error("RedisServer:" + getMasterAddressPort(), e);
				}
			}
			
			if (!excuteSucc && (curTryTimes >= AppCanstant.MAXTRYTIMES)) {
				StackTraceElement[] stackTrace = Thread.currentThread().getStackTrace();
				if (stackTrace != null) {
					StringBuffer buffer = new StringBuffer();
					for (StackTraceElement element:stackTrace) {
						buffer.append(element.getClassName() + "." + element.getMethodName() + " " + element.getLineNumber());
						buffer.append("\n");
					}
					logger.error("连续执行三次失败:\n" + buffer);
				}
				JSONObject json = new JSONObject();
				json.put("errorType", "redis");
				json.put("className", this.getClass().getSimpleName());
				json.put("numCnt", this.getNumCnt());
				json.put("method", "getList(RedisScript<List> script, List<String> keys, Object... objects)");
				
				json.put("script", script.getScriptAsString());
				JSONArray arrayKey = new JSONArray();
				for(String key:keys){
					arrayKey.add(key);
					}
				json.put("keys", arrayKey);
				JSONArray arrayObject = new JSONArray();
				if (objects != null) {
					for (int i = 0; i < objects.length; i++) {
						arrayObject.add(objects[i]);
					}
				}
				json.put("objects", arrayObject);
				logger.error(json.toJSONString());
				configInit.initRedis(this.getNumCnt());
			}
			
		} while (!excuteSucc && (curTryTimes < AppCanstant.MAXTRYTIMES));
		
		return result;
	}
	
	@SuppressWarnings({ "rawtypes", "unchecked" })
	public List<Long> getListLong(RedisScript<List> script, List<String> keys, Object... objects) {
		
		long curTryTimes = 0;
		
		boolean excuteSucc = false;
		
		List<Long> result = new ArrayList<Long>();
		
		do {
			try {
				curTryTimes ++;
				result = redisTemplate.execute(script, keys, objects);
				excuteSucc = true;
			} catch (Exception e) {
				if (e instanceof RedisConnectionFailureException) {
					excuteSucc = false;
					logger.error("从JedisPool获取连接失败, 尝试获取连接:" + curTryTimes + "次! RedisServer:" + getMasterAddressPort());
				} else if (e instanceof SocketTimeoutException) {
					excuteSucc = true;
					logger.error("SoketTimeout,命令已经发送到Redis上执行,但是在等待执行结果的时候SocketRead超时! RedisServer:" + getMasterAddressPort(), e);
				} else {
					excuteSucc = false;
					logger.error("RedisServer:" + getMasterAddressPort(), e);
				}
			}
			
			if (!excuteSucc && (curTryTimes >= AppCanstant.MAXTRYTIMES)) {
				StackTraceElement[] stackTrace = Thread.currentThread().getStackTrace();
				if (stackTrace != null) {
					StringBuffer buffer = new StringBuffer();
					for (StackTraceElement element:stackTrace) {
						buffer.append(element.getClassName() + "." + element.getMethodName() + " " + element.getLineNumber());
						buffer.append("\n");
					}
					logger.error("连续执行三次失败:\n" + buffer);
				}
				JSONObject json = new JSONObject();
				json.put("errorType", "redis");
				json.put("className", this.getClass().getSimpleName());
				json.put("numCnt", this.getNumCnt());
				json.put("method", "getListLong(RedisScript<List> script, List<String> keys, Object... objects)");
				
				json.put("script", script.getScriptAsString());
				JSONArray arrayKey = new JSONArray();
				for(String key:keys){
					arrayKey.add(key);
					}
				json.put("keys", arrayKey);
				JSONArray arrayObject = new JSONArray();
				if (objects != null) {
					for (int i = 0; i < objects.length; i++) {
						arrayObject.add(objects[i]);
					}
				}
				json.put("objects", arrayObject);
				logger.error(json.toJSONString());
				configInit.initRedis(this.getNumCnt());
			}
			
		} while (!excuteSucc && (curTryTimes < AppCanstant.MAXTRYTIMES));
		
		return result;
	}
	
}
